/*
 * @Author: gggg 1263457581@qq.com
 * @Date: 2025-06-09 10:41:18
 * @LastEditors: gggg 1263457581@qq.com
 * @LastEditTime: 2025-06-10 17:30:47
 * @FilePath: /algorithm-and-data-struct/pool/ThreadPool.cpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <iostream>
#include <thread>
#include <vector>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <functional>

class ThreadPool {
public:
    ThreadPool(size_t threads); // 构造函数，初始化线程数
    template<class F, class... Args>
    void enqueue(F&& f, Args&&... args); // 添加任务到队列
    ~ThreadPool(); // 析构函数，等待所有任务完成并清理资源
    
private:
    std::vector<std::thread> workers; // 工作线程向量
    std::queue<std::function<void()>> tasks; // 任务队列
    
    // 同步原语
    std::mutex queueMutex; // 队列互斥锁
    std::condition_variable condition; // 条件变量，用于通知等待的线程
    bool stop = false; // 标志位，用于通知线程停止工作
    
    void worker(); // 工作线程执行的函数
};

ThreadPool::ThreadPool(size_t threads) : stop(false) {
    for (size_t i = 0; i < threads; ++i) {
        workers.emplace_back([this] { worker(); }); // 创建并启动工作线程
    }
}
 
ThreadPool::~ThreadPool() {
    {
        std::unique_lock<std::mutex> lock(queueMutex);
        stop = true; // 设置停止标志位
    }
    condition.notify_all(); // 通知所有等待的线程
    for (std::thread &worker : workers) {
        worker.join(); // 等待所有线程完成
    }
}

void ThreadPool::worker() {
    while (true) {
        std::function<void()> task;
        {
            std::unique_lock<std::mutex> lock(queueMutex); // 获取互斥锁以保护队列访问
            condition.wait(lock, [this] { return stop || !tasks.empty(); }); // 等待有任务或停止信号
            if (stop && tasks.empty()) return; // 如果停止并且没有任务，则退出线程
            task = std::move(tasks.front()); // 获取任务并从队列中移除它
            tasks.pop(); // 弹出任务
        }
        task(); // 执行任务
    }
}
 
template<class F, class... Args>
void ThreadPool::enqueue(F&& f, Args&&... args) {
    std::function<void()> task(std::bind(std::forward<F>(f), std::forward<Args>(args)...)); // 创建可调用对象任务并封装到std::function中
    {
        std::unique_lock<std::mutex> lock(queueMutex); // 获取互斥锁以保护队列访问和条件变量通知操作
        if (stop) throw std::runtime_error("Enqueue on stopped ThreadPool"); // 如果已停止，抛出异常
        tasks.emplace(task); // 将任务加入队列中
    }
    condition.notify_one(); // 通知一个等待的线程有新任务可用
}


int main() {
    ThreadPool pool(4); // 创建包含4个工作线程的线程池
    for (int i = 0; i < 8; ++i) { // 添加8个任务到线程池中执行（每个任务打印它的索引）
        pool.enqueue([i] { std::cout << "Task " << i << " executed\n"; }); // 使用lambda表达式封装任务函数，并传递索引i作为参数。
    }
    return 0; // 主
}